GRAPHS

Philippine Kidnappings

computed layouts

Photo from Wikipedia

Photo from Wikipedia

…didn’t pursue us…As time went on, we noticed that they never pursued us…
— Gracia Burnham, ASG kidnap survivor


Data refers to the Abu Sayyaf Group (ASG), a violent non-state actor operating in the Southern Philippines. In particular, this data is related to the Salast movement that has been founded by Aburajak Janjalani, a native terrorist of the Southern Philippines in 1991. ASG is active in kidnapping and other kinds of terrorist attacks (Gerdes et al. 2014). Nodes are terrorist kidnappers of the ASG. Edges are the terrorist events they have attended. This network describes how many events any two kidnappers have in common.

uses original data and network science to assess aspects of ASG’s strategic capabilities. More specifically, network simulations of agent-level data serve to measure the extent to which ASG’s observed pattern of disseminating hands-on operational knowledge differs from random.

ASG began kidnapping hostages soon after its founding.

  • an American missionary in Sulu in 1993,
  • five Americans and 11 Filipinos at Trankini Falls, a popular nature spot near Lake Sebu, in 1995
  • nearly 60 teachers and school children in Sumisip in 2000;
  • 21 tourists from a dive-resort on the Malaysian island of Sipadan later that year;
  • another 20 tourists, including three Americans, from the Dos Palmas Beach Resort on Palawan in 2001.
  • a myriad lower-profile kidnappings for ransom with victims such as Filipino businessmen,news reporters, and Christian clergy members.

The most important component of the original data was the agent x event matrix, which provides a tabular listing of the individuals who participated in each event, as well as the location where each interaction occurred.

DATA: 2-model matrix 246x105 persons by terrorist events, undirected binary relations are participation in events. The PK network has 246 nodes and 2571 edges.

An incidence matrix is not square and entities provided in rows and columns are not necessary the same.

Ingest

agent × event data

df_path <- "archetypes/philippine-kidnappings/philippine-kidnappings.csv"
df_csv <- read.csv(df_path, header=TRUE, row.names=1, check.names=FALSE, na.strings = "")
df_csv
df_nodes_path <- "archetypes/philippine-kidnappings/philippine-kidnappings-nodes.csv"
df_nodes <- read.csv(df_nodes_path, header = TRUE, stringsAsFactors = FALSE)
df_nodes
df_edges_path <- "archetypes/philippine-kidnappings/philippine-kidnappings-edges.csv"
df_edges <- read.csv(df_edges_path, header = TRUE, stringsAsFactors = FALSE)
df_edges

Wrangle

convert matrix to graph, filter by degree

df_csv[is.na(df_csv)] <- 0
matrix <- as.matrix(df_csv) 
df_graph <- graph_from_incidence_matrix(matrix)
df_graph
## IGRAPH 7990767 UN-B 351 402 -- 
## + attr: type (v/l), name (v/c)
## + edges from 7990767 (vertex names):
##  [1] N1 --E23 N1 --E33 N1 --E41 N1 --E42 N1 --E44 N2 --E23 N2 --E33 N3 --E6 
##  [9] N3 --E9  N3 --E10 N3 --E14 N3 --E19 N3 --E25 N3 --E28 N3 --E31 N3 --E32
## [17] N4 --E1  N4 --E30 N4 --E34 N5 --E1  N5 --E2  N5 --E4  N5 --E8  N6 --E8 
## [25] N6 --E9  N6 --E10 N6 --E11 N7 --E4  N7 --E8  N8 --E8  N9 --E4  N9 --E12
## [33] N9 --E30 N9 --E39 N10--E26 N10--E32 N10--E41 N10--E42 N10--E43 N10--E65
## [41] N10--E79 N11--E3  N12--E3  N13--E32 N13--E35 N13--E67 N14--E3  N15--E3 
## [49] N16--E3  N17--E6  N18--E27 N18--E35 N19--E6  N19--E9  N19--E12 N19--E25
## [57] N19--E29 N19--E32 N20--E6  N21--E30 N22--E27 N23--E27 N23--E30 N23--E35
## + ... omitted several edges
# less than 3 degrees
three_degrees <- which(degree(df_graph)<3)
df_graph <- delete.vertices(df_graph, three_degrees)

# remove isolates
isolates <- which(degree(df_graph)==0)
df_graph <- delete.vertices(df_graph, isolates)


df_graph_manual <- graph_from_data_frame( df_edges, vertices=df_nodes )

Analytics

compute sna measures

Analytics

compute layout

# igraph layouts

# bipartite <- create_layout(df_graph, layout = 'igraph', algorithm = 'bipartite')
circle <- create_layout(df_graph, layout = 'igraph', algorithm = 'circle')
dh <- create_layout(df_graph, layout = 'igraph', algorithm = 'dh')
# drl <- create_layout(df_graph, layout = 'igraph', algorithm = 'drl')
fr <- create_layout(df_graph, layout = 'igraph', algorithm = 'fr')
gem <- create_layout(df_graph, layout = 'igraph', algorithm = 'gem')
graphopt <- create_layout(df_graph, layout = 'igraph', algorithm = 'graphopt')
# grid <- create_layout(df_graph, layout = 'igraph', algorithm = 'grid')
kk <- create_layout(df_graph, layout = 'igraph', algorithm = 'kk')
# lgl <- create_layout(df_graph, layout = 'igraph', algorithm = 'lgl')
# mds <- create_layout(df_graph, layout = 'igraph', algorithm = 'mds')
nicely <- create_layout(df_graph, layout = 'igraph', algorithm = 'nicely')
# sphere <- create_layout(df_graph, layout = 'igraph', algorithm = 'sphere')
# star <- create_layout(df_graph, layout = 'igraph', algorithm = 'star')
sugiyama <- create_layout(df_graph, layout = 'igraph', algorithm = 'sugiyama')

# ggraph layouts

# backbone <- create_layout(df_graph_undirected, layout = 'backbone')
# centrality_bc <- betweenness(df_graph)
# centrality <- create_layout(df_graph, layout = 'centrality', centrality = centrality_bc)
# eigen <- create_layout(df_graph, layout = 'eigen', type = "laplacian", eigenvector = "smallest")
# fabric <- create_layout(df_graph, layout = 'fabric')
# focus <- create_layout(df_graph_directed, layout = 'focus', focus = 1)
# hive <- create_layout(df_graph, layout = 'hive', axis = friends, sort.by = degree)
# linear <- create_layout(df_graph, layout = 'linear')
# matrix <- create_layout(df_graph, layout = 'matrix')
# pmds_pivots <- 3
# pmds <- create_layout(df_graph, layout = 'pmds', pivots = pmds_pivots)
stress <- create_layout(df_graph, layout = 'stress')
# unrooted <- create_layout(df_graph, layout = 'unrooted' )

stress_m <- create_layout(df_graph_manual, layout = 'stress')
# Edge Types
# geom_edge_arc
# geom_edge_arc0
# geom_edge_arc2
# geom_edge_density
# geom_edge_diagonal
# geom_edge_diagonal0
# geom_edge_diagonal2
# geom_edge_elbow
# geom_edge_elbow0
# geom_edge_elbow2
# geom_edge_fan
# geom_edge_fan0
# geom_edge_fan2
# geom_edge_hive
# geom_edge_hive0
# geom_edge_hive2
# geom_edge_link
# geom_edge_link0
# geom_edge_link2
# geom_edge_loop
# geom_edge_loop0

Plot

nicely

theme_opts <- theme(
    text = element_text(family = "inconsolata"), 
    # plot.margin = unit(c(1.5,1,1,1), "in"),
    legend.position='none'
)

v1 <- ggraph(circle) + 
  geom_edge_link() +
  geom_node_point(size = 2) +
  geom_node_label(aes(label = name), size = 4) +
  theme_graph() +
  theme_opts

girafe(ggobj = v1, width_svg = 1280/72, height_svg = 720/72,
       options = list(opts_sizing(rescale = TRUE, width = 1.0))
)
v2 <- ggraph(stress_m) + 
  geom_edge_link() +
  geom_node_point(size = 2) +
  geom_node_label(aes(label = NODE_NAME), size = 2) +
  theme_graph() +
  theme_opts

girafe(ggobj = v2, width_svg = 1280/72, height_svg = 720/72,
       options = list(opts_sizing(rescale = TRUE, width = 1.0))
)

References

citations for narrative and data sources